home *** CD-ROM | disk | FTP | other *** search
Wrap
/********************************************************************** * ISO MPEG Audio Subgroup Software Simulation Group (1996) * ISO 13818-3 MPEG-2 Audio Encoder - Lower Sampling Frequency Extension * * $Id: l3psy.c,v 1.2 1998/10/05 17:06:48 larsi Exp $ * * $Log: l3psy.c,v $ * Revision 1.2 1998/10/05 17:06:48 larsi * *** empty log message *** * * Revision 1.1.1.1 1998/10/05 14:47:18 larsi * * Revision 1.2 1997/01/19 22:28:29 rowlands * Layer 3 bug fixes from Seymour Shlien * * Revision 1.1 1996/02/14 04:04:23 rowlands * Initial revision * * Received from Mike Coleman **********************************************************************/ /********************************************************************** * date programmers comment * * 2/25/91 Davis Pan start of version 1.0 records * * 5/10/91 W. Joseph Carter Ported to Macintosh and Unix. * * 7/10/91 Earle Jennings Ported to MsDos. * * replace of floats with FLOAT * * 2/11/92 W. Joseph Carter Fixed mem_alloc() arg for "absthr". * * 3/16/92 Masahiro Iwadare Modification for Layer III * * 17/4/93 Masahiro Iwadare Updated for IS Modification * **********************************************************************/ #include "common.h" #include "globalflags.h" #include "encoder.h" #include "l3psy.h" #include "l3side.h" #include <assert.h> #include "gtkanal.h" #define MSFREQ 20 #define maximum(x,y) ( (x>y) ? x : y ) #define minimum(x,y) ( (x<y) ? x : y ) /* some different types of adaptive window switching */ /* This mode will turn on short_blocks if there is a localized surge in energy */ #define ENER_AWS /* from Gabriel Bouvigne <bouvigne@multimania.com> */ #define AWS static int switch_pe=1800; void sprdngf1(FLOAT *, double *); void sprdngf2(double *, FLOAT *); static double s3_l[CBANDS][CBANDS]; /* needed global static by sprdngfs */ void L3para_read( double sfreq, int numlines[CBANDS], int partition_l[HBLKSIZE], double minval[CBANDS], double qthr_l[CBANDS], double norm_l[CBANDS], double s3_l[CBANDS][CBANDS], int partition_s[HBLKSIZE_s], double qthr_s[CBANDS_s], double norm_s[CBANDS_s], double SNR_s[CBANDS_s], int cbw_l[SBMAX_l], int bu_l[SBMAX_l], int bo_l[SBMAX_l], double w1_l[SBMAX_l], double w2_l[SBMAX_l], int cbw_s[SBMAX_s], int bu_s[SBMAX_s], int bo_s[SBMAX_s], double w1_s[SBMAX_s], double w2_s[SBMAX_s] ); void L3psycho_energy( short int *buffer, FLOAT energy[HBLKSIZE], FLOAT ax[HBLKSIZE], FLOAT bx[HBLKSIZE], FLOAT energy_s[3][HBLKSIZE_s], FLOAT ax_s[3][HBLKSIZE_s], FLOAT bx_s[3][HBLKSIZE_s], int chn,int gr , layer * info, int check_ms_stereo, double *ms_ener_ratio) { static short int savebuffer[2][1344]; static double ms_ener[2]; static int sync_flush,flush,syncsize; static int init=0; static FLOAT scalefac; static FLOAT window_s[BLKSIZE_s]; static FLOAT window[BLKSIZE]; #ifdef HAVEGTK static FLOAT energy_save[2][HBLKSIZE]; #endif short int *savebuf; int i,j,k,sblock; static FLOAT wsamp_r_int[2][BLKSIZE]; FLOAT wsamp_rs[256],*wsamp_r; wsamp_r=wsamp_r_int[chn]; savebuf = &savebuffer[chn][0]; if(init==0){ init=1; memset((char *) savebuffer, 0, sizeof(savebuffer)); if (gpsycho) {sync_flush=WINDELAY; flush=576; syncsize=WINDELAY+576;} else {sync_flush=768; flush=576; syncsize=1344;} scalefac=1.0; if (force_ms) scalefac=sqrt(2.0); /* calculate HANN window coefficients */ /* for(i=0;i<BLKSIZE;i++) window[i] =0.5*(1-cos(2.0*PI*i/(BLKSIZE-1.0)));*/ for(i=0;i<BLKSIZE;i++) window[i] =0.5*(1-cos(2.0*PI*(i-0.5)/BLKSIZE)); for(i=0;i<BLKSIZE_s;i++)window_s[i]=0.5*(1-cos(2.0*PI*(i-0.5)/BLKSIZE_s)); } /********************************************************************** * Delay signal by sync_flush samples * **********************************************************************/ for ( j = 0; j < sync_flush; j++ ) /* for long window samples */ savebuf[j] = savebuf[j+flush]; for ( j = sync_flush; j < syncsize; j++ ) savebuf[j] = buffer[j-sync_flush]; /********************************************************************** * compute FFTs **********************************************************************/ for ( j = 0; j < BLKSIZE; j++ ) wsamp_r[j] = window[j] * savebuf[j] * scalefac; fft( wsamp_r, energy, ax, bx, 1024 ); /**long FFT**/ #ifdef HAVEGTK /* delay by one granule. Note we have to 'toggle' gr to do this */ if(gtkflag) { for (j=0; j<HBLKSIZE ; j++) { pinfo->energy[1-gr][chn][j]=energy_save[chn][j]; energy_save[chn][j]=energy[j]; } } #endif for ( sblock = 0; sblock < 3; sblock++ ) { int shlen = 128; int shoff = 2; if (gpsycho) { shlen = 192; shoff = 1; } for ( j = 0, k = shlen * (shoff + sblock); j < 256; j++, k++ ) wsamp_rs[j] = window_s[j]* savebuf[k]*scalefac; fft( wsamp_rs, &energy_s[sblock][0], &ax_s[sblock][0], &bx_s[sblock][0], 256 ); } /**********************************************************************/ /* compute side_energy / total_energy ratio */ /**********************************************************************/ *ms_ener_ratio=0; if (check_ms_stereo) { double ms_ener_side; /* compute energy in frequencies above MSFREQ */ for (ms_ener[chn]=0, j=MSFREQ; j<HBLKSIZE ; j++) { ms_ener[chn] += energy[j]; } if (chn == 1) { /* compute energy in side channel */ ms_ener_side = fft_side( wsamp_r_int, MSFREQ); /* ener_side / total_energy */ if (ms_ener_side <= .01*(ms_ener[0]+ms_ener[1])) ms_ener_side = .01; else *ms_ener_ratio = ms_ener_side/(ms_ener[0]+ms_ener[1]); } } if (force_ms) { for (ms_ener[chn]=0, j=MSFREQ; j<HBLKSIZE ; j++) ms_ener[chn] += energy[j]; if (chn == 1) if (ms_ener[1] <= .01*(ms_ener[0]+ms_ener[1])) *ms_ener_ratio = .01; else *ms_ener_ratio = ms_ener[1]/(ms_ener[0]+ms_ener[1]); } } void L3psycho_anal( short int *buffer[2], int stereo, int gr , layer * info, double sfreq, int check_ms_stereo, double *ms_ener_ratio, double ratio_d[2][21], double ratio_ds[2][12][3], double percep_energy[2], int blocktype_d[2]) { static double pe[2]={0,0}; static double ms_ratio_s_old=0,ms_ratio_l_old=0; static double ratio[2][SBMAX_l]; static double ratio_s[2][SBMAX_s][3]; #ifdef HAVEGTK static double pe_save[2]; static double ers_save[2]; #endif static double thm_save[2][SBMAX_l]; static double en_save[2][SBMAX_l]; static double thm_s_save[2][SBMAX_s][3]; static double en_s_save[2][SBMAX_s][3]; int blocktype[2],uselongblock[2],chn; unsigned int b, i, j, k; FLOAT freq_mult, bval_lo; double temp1,temp2,temp3; double ms_ratio_l=0,ms_ratio_s=0; /* nint(); Layer III */ double thr[CBANDS]; FLOAT ax[HBLKSIZE], bx[HBLKSIZE]; FLOAT energy[HBLKSIZE]; FLOAT energy_s[3][HBLKSIZE_s]; FLOAT ax_s[3][HBLKSIZE_s], bx_s[3][HBLKSIZE_s]; /* 256 samples not 129. */ static float mld_l[SBMAX_l],mld_s[SBMAX_s]; /* The static variables "r", "phi_sav", "new", "old" and "oldest" have */ /* to be remembered for the unpredictability measure. For "r" and */ /* "phi_sav", the first index from the left is the channel select and */ /* the second index is the "age" of the data. */ static int new = 0, old = 1, oldest = 0; static int init = 0, sfreq_idx; static double cw[HBLKSIZE], eb[CBANDS]; static double ctb[CBANDS]; static double SNR_l[CBANDS], SNR_s[CBANDS_s]; static int init_L3; static double minval[CBANDS],qthr_l[CBANDS],norm_l[CBANDS]; static double qthr_s[CBANDS_s],norm_s[CBANDS_s]; static double nb_1[2][CBANDS], nb_2[2][CBANDS]; /* Scale Factor Bands */ static int cbw_l[SBMAX_l],bu_l[SBMAX_l],bo_l[SBMAX_l] ; static int cbw_s[SBMAX_s],bu_s[SBMAX_s],bo_s[SBMAX_s] ; static double w1_l[SBMAX_l], w2_l[SBMAX_l]; static double w1_s[SBMAX_s], w2_s[SBMAX_s]; static double en[SBMAX_l], thm[SBMAX_l] ; static int blocktype_old[2] ; int sb,sblock; static int partition_l[HBLKSIZE],partition_s[HBLKSIZE_s]; /* The following static variables are constants. */ static FLOAT crit_band[27] = {0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270,1480,1720,2000,2320, 2700, 3150, 3700, 4400,5300,6400,7700,9500,12000, 15500,25000,30000}; static FLOAT *nb, *cb, *ecb, *bc; static FLOAT *c, *fthr; static F32 *snrtmp; static int *numlines ; static int *numlines2 ; static int *partition; static FLOAT *cbval, *rnorm; static FLOAT *absthr; static double *tmn; static FCB *s; static FHBLK *lthr; static F2HBLK *ax_sav, *bx_sav, *rx_sav; assert( info->lay == 3 ); if(init==0){ /* These dynamic memory allocations simulate "static" variables placed */ /* in the data space. Each mem_alloc() call here occurs only once at */ /* initialization time. The mem_free() function must not be called. */ nb = (FLOAT *) mem_alloc(sizeof(FCB), "nb"); cb = (FLOAT *) mem_alloc(sizeof(FCB), "cb"); ecb = (FLOAT *) mem_alloc(sizeof(FCB), "ecb"); bc = (FLOAT *) mem_alloc(sizeof(FCB), "bc"); c = (FLOAT *) mem_alloc(sizeof(FHBLK), "c"); fthr = (FLOAT *) mem_alloc(sizeof(FHBLK), "fthr"); snrtmp = (F32 *) mem_alloc(sizeof(F2_32), "snrtmp"); numlines = (int *) mem_alloc(sizeof(ICB), "numlines"); if (gpsycho) numlines2 = (int *) mem_alloc(sizeof(ICB), "numlines"); else /* ISO model overwrites numlines with garbage */ numlines2 = numlines; partition = (int *) mem_alloc(sizeof(IHBLK), "partition"); cbval = (FLOAT *) mem_alloc(sizeof(FCB), "cbval"); rnorm = (FLOAT *) mem_alloc(sizeof(FCB), "rnorm"); absthr = (FLOAT *) mem_alloc(sizeof(FHBLK), "absthr"); tmn = (double *) mem_alloc(sizeof(DCB), "tmn"); s = (FCB *) mem_alloc(sizeof(FCBCB), "s"); lthr = (FHBLK *) mem_alloc(sizeof(F2HBLK), "lthr"); rx_sav = (F2HBLK *) mem_alloc(sizeof(F22HBLK), "rx_sav"); ax_sav = (F2HBLK *) mem_alloc(sizeof(F22HBLK), "ax_sav"); bx_sav = (F2HBLK *) mem_alloc(sizeof(F22HBLK), "bx_sav"); i = sfreq + 0.5; switch(i){ case 32000: sfreq_idx = 0; break; case 44100: sfreq_idx = 1; break; case 48000: sfreq_idx = 2; break; default: printf("error, invalid sampling frequency: %d Hz\n",i); exit(-1); } /* printf("absthr[][] sampling frequency index: %d\n",sfreq_idx); */ read_absthr(absthr, sfreq_idx); /* reset states used in unpredictability measure */ memset (rx_sav,0, 4* HBLKSIZE); memset (ax_sav,0, 4* HBLKSIZE); memset (bx_sav,0, 4* HBLKSIZE); for(i=0;i<HBLKSIZE;i++){ lthr[0][i] = 60802371420160.0; lthr[1][i] = 60802371420160.0; } /***************************************************************************** * Initialization: Compute the following constants for use later * * partition[HBLKSIZE] = the partition number associated with each * * frequency line * * cbval[CBANDS] = the center (average) bark value of each * * partition * * numlines[CBANDS] = the number of frequency lines in each partition * * tmn[CBANDS] = tone masking noise * *****************************************************************************/ /* compute fft frequency multiplicand */ freq_mult = sfreq/BLKSIZE; /* calculate fft frequency, then bval of each line (use fthr[] as tmp storage)*/ for(i=0;i<HBLKSIZE;i++){ temp1 = i*freq_mult; j = 1; while(temp1>crit_band[j])j++; fthr[i]=j-1+(temp1-crit_band[j-1])/(crit_band[j]-crit_band[j-1]); } partition[0] = 0; /* temp2 is the counter of the number of frequency lines in each partition */ temp2 = 1; cbval[0]=fthr[0]; bval_lo=fthr[0]; for(i=1;i<HBLKSIZE;i++){ if((fthr[i]-bval_lo)>0.33){ partition[i]=partition[i-1]+1; cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; cbval[partition[i]] = fthr[i]; bval_lo = fthr[i]; numlines[partition[i-1]] = temp2; temp2 = 1; } else { partition[i]=partition[i-1]; cbval[partition[i]] += fthr[i]; temp2++; } } numlines[partition[i-1]] = temp2; cbval[partition[i-1]] = cbval[partition[i-1]]/temp2; /************************************************************************ * Now compute the spreading function, s[j][i], the value of the spread-* * ing function, centered at band j, for band i, store for later use * ************************************************************************/ for(j=0;j<CBANDS;j++){ for(i=0;i<CBANDS;i++){ temp1 = (cbval[i] - cbval[j])*1.05; if(temp1>=0.5 && temp1<=2.5){ temp2 = temp1 - 0.5; temp2 = 8.0 * (temp2*(temp2 - 2.0)); } else temp2 = 0; temp1 += 0.474; temp3 = 15.811389+7.5*temp1-17.5*sqrt((double) (1.0+temp1*temp1)); if(temp3 <= -100) s[i][j] = 0; else { temp3 = (temp2 + temp3)*LN_TO_LOG10; s[i][j] = exp(temp3); } } } /* Calculate Tone Masking Noise values */ for(j=0;j<CBANDS;j++){ temp1 = 15.5 + cbval[j]; tmn[j] = (temp1>24.5) ? temp1 : 24.5; /* Calculate normalization factors for the net spreading functions */ rnorm[j] = 0; for(i=0;i<CBANDS;i++){ rnorm[j] += s[j][i]; } } /* setup stereo demasking thresholds */ /* formula reverse enginerred from plot in paper */ for ( sb = 0; sb < SBMAX_s; sb++ ) { double mld = 1.25*(1-cos(3.14159*sb/SBMAX_s))-2.5; mld_s[sb] = pow(10.0,mld); } for ( sb = 0; sb < SBMAX_l; sb++ ) { double mld = 1.25*(1-cos(3.14159*sb/SBMAX_l))-2.5; mld_l[sb] = pow(10.0,mld); } init++; } if ( init_L3 == 0 ) { L3para_read( sfreq,numlines2,partition_l,minval,qthr_l,norm_l,s3_l, partition_s,qthr_s,norm_s,SNR_s, cbw_l,bu_l,bo_l,w1_l,w2_l, cbw_s,bu_s,bo_s,w1_s,w2_s ); init_L3 ++ ; } /************************* End of Initialization *****************************/ #ifdef AWS /* reduce switch_pe if there where preecho events in previous granules */ if (gpsycho) { int prev_granule_used_shortblock=0; for (chn=0; chn<stereo; chn++) if (blocktype_old[chn]==SHORT_TYPE) prev_granule_used_shortblock=1; if (prev_granule_used_shortblock) switch_pe=maximum(switch_pe-700,900); else switch_pe = minimum(switch_pe+200,1800); } #endif for (chn=0; chn<stereo; chn++) { for ( j = 0; j < 21; j++ ) ratio_d[chn][j] = ratio[chn][j]; for ( j = 0; j < 12; j++ ) for ( i = 0; i < 3; i++ ) ratio_ds[chn][j][i] = ratio_s[chn][j][i]; /* buggy ISO model doesn't delay pe */ if (gpsycho) percep_energy[chn] = pe[chn]; /*if ( chn == 0 )*/ if ( new == 0 ) { new = 1; old = 0; oldest = 1; } else { new = 0; old = 1; oldest = 0; } /********************************************************************** * compute FFTs **********************************************************************/ L3psycho_energy( buffer[chn], energy, ax, bx, energy_s, ax_s, bx_s, chn,gr,info,check_ms_stereo,&ms_ratio_l); ms_ratio_s=ms_ratio_l; /********************************************************************** * compute unpredicatability of first six spectral lines * **********************************************************************/ for ( j = 0; j < 6; j++ ) { /* calculate unpredictability measure cw */ double an, a1, a2; double bn, b1, b2; double rn, r1, r2; double numre, numim, den; a2 = ax_sav[chn][oldest][j]; b2 = bx_sav[chn][oldest][j]; r2 = rx_sav[chn][oldest][j]; a1 = ax_sav[chn][oldest][j] = ax_sav[chn][old][j]; b1 = bx_sav[chn][oldest][j] = bx_sav[chn][old][j]; r1 = rx_sav[chn][oldest][j] = rx_sav[chn][old][j]; an = ax_sav[chn][old][j] = ax[j]; bn = bx_sav[chn][old][j] = bx[j]; rn = rx_sav[chn][old][j] = sqrt(energy[j]); { /* square (x1,y1) */ if( r1 != 0.0 ) { numre = (a1*b1); numim = (a1*a1-b1*b1)*0.5; den = r1*r1; } else { numre = 1.0; numim = 0.0; den = 1.0; } } { /* multiply by (x2,-y2) */ if( r2 != 0.0 ) { double tmp2 = (numim+numre)*(a2+b2)*0.5; double tmp1 = -a2*numre+tmp2; numre = -b2*numim+tmp2; numim = tmp1; den *= r2; } else { /* do nothing */ } } { /* r-prime factor */ double tmp = (2.0*r1-r2)/den; numre *= tmp; numim *= tmp; } if( (den=rn+fabs(2.0*r1-r2)) != 0.0 ) { numre = (an+bn)/2.0-numre; numim = (an-bn)/2.0-numim; cw[j] = sqrt(numre*numre+numim*numim)/den; } else { cw[j] = 0.0; } } /********************************************************************** * compute unpredicatibility of next 200 spectral lines * **********************************************************************/ sblock = 1; for ( j = 6; j < 206; j += 4 ) {/* calculate unpredictability measure cw */ double rn, r1, r2; double numre, numim, den; k = (j+2) / 4; { /* square (x1,y1) */ r1 = sqrt((double)energy_s[0][k]); if( r1 != 0.0 ) { double a1 = ax_s[0][k]; double b1 = bx_s[0][k]; numre = (a1*b1); numim = (a1*a1-b1*b1)*0.5; den = r1*r1; } else { numre = 1.0; numim = 0.0; den = 1.0; } } { /* multiply by (x2,-y2) */ r2 = sqrt((double)energy_s[2][k]); if( r2 != 0.0 ) { double a2 = ax_s[2][k]; double b2 = bx_s[2][k]; double tmp2 = (numim+numre)*(a2+b2)*0.5; double tmp1 = -a2*numre+tmp2; numre = -b2*numim+tmp2; numim = tmp1; den *= r2; } else { /* do nothing */ } } { /* r-prime factor */ double tmp = (2.0*r1-r2)/den; numre *= tmp; numim *= tmp; } rn = sqrt((double)energy_s[1][k]); if( (den=rn+fabs(2.0*r1-r2)) != 0.0 ) { double an = ax_s[1][k]; double bn = bx_s[1][k]; numre = (an+bn)/2.0-numre; numim = (an-bn)/2.0-numim; cw[j] = sqrt(numre*numre+numim*numim)/den; } else { cw[j] = 0.0; } cw[j+1] = cw[j+2] = cw[j+3] = cw[j]; } /********************************************************************** * Set unpredicatiblility of remaining spectral lines to 0.4 206..513 * **********************************************************************/ for ( j = 206; j < HBLKSIZE; j++ ) cw[j] = 0.4; #if 0 for ( j = 14; j < HBLKSIZE-4; j += 4 ) {/* calculate energy from short ffts */ double tot,ave; k = (j+2) / 4; for (tot=0, sblock=0; sblock < 3; sblock++) tot+=energy_s[sblock][k]; ave = energy[j+1]+ energy[j+2]+ energy[j+3]+ energy[j]; ave /= 4.; /* printf("energy / tot %i %5.2f %e %e\n",j,ave/(tot*16./3.), ave,tot*16./3.); */ energy[j+1] = energy[j+2] = energy[j+3] = energy[j]=tot; } #endif /********************************************************************** * Calculate the energy and the unpredictability in the threshold * * calculation partitions * **********************************************************************/ for ( b = 0; b < CBANDS; b++ ) { eb[b] = 0.0; cb[b] = 0.0; } for ( j = 0; j < HBLKSIZE; j++ ) { int tp = partition_l[j]; if ( tp >= 0 ) { eb[tp] += energy[j]; cb[tp] += cw[j] * energy[j]; } } /********************************************************************** * convolve the partitioned energy and unpredictability * * with the spreading function, s3_l[b][k] * ******************************************************************** */ for ( b = 0; b < CBANDS; b++ ) { ecb[b] = 0.0; ctb[b] = 0.0; } /* s3_l is a sparse matrix for 44.1khz */ if (sfreq_idx==1) { sprdngf1(ecb,eb); sprdngf2(ctb,cb); } else { for ( b = 0;b < CBANDS; b++ ) { for ( k = 0; k < CBANDS; k++ ) { ecb[b] += s3_l[b][k] * eb[k]; /* sprdngf for Layer III */ ctb[b] += s3_l[b][k] * cb[k]; } } } /* calculate the tonality of each threshold calculation partition */ /* calculate the SNR in each threshhold calculation partition */ for ( b = 0; b < CBANDS; b++ ) { double cbb,tbb; if (ecb[b] != 0.0 ) { cbb = ctb[b]/ecb[b]; if (cbb <0.01) cbb = 0.01; cbb = log( cbb); } else cbb = 0.0 ; tbb = -0.299 - 0.43*cbb; /* conv1=-0.299, conv2=-0.43 */ tbb = minimum( 1.0, maximum( 0.0, tbb) ) ; /* 0<tbb<1 */ SNR_l[b] = maximum( minval[b], 29.0*tbb+6.0*(1.0-tbb) ); } /* TMN=29.0,NMT=6.0 for all calculation partitions */ for ( b = 0; b < CBANDS; b++ ) /* calculate the threshold for each partition */ nb[b] = ecb[b] * norm_l[b] * exp( -SNR_l[b] * LN_TO_LOG10 ); for ( b = 0; b < CBANDS; b++ ) { /* pre-echo control */ double temp_1; /* BUG of IS */ int rpelev=2; int rpelev2=16; temp_1 = minimum( nb[b], minimum(rpelev*nb_1[chn][b],rpelev2*nb_2[chn][b]) ); thr[b] = maximum( qthr_l[b], temp_1 );/* rpelev=2.0, rpelev2=16.0 */ nb_2[chn][b] = nb_1[chn][b]; nb_1[chn][b] = nb[b]; } /* note: all surges in PE are because of the above pre-echo formula * for temp_1. it this is not used, PE is always around 600 */ pe[chn] = 0.0; /* calculate percetual entropy */ for ( b = 0; b < CBANDS; b++ ) { double tp ; tp = minimum( 0.0, log((thr[b]+1.0) / (eb[b]+1.0) ) ) ; /*not log*/ pe[chn] -= numlines[b] * tp ; } /* thr[b] -> thr[b]+1.0 : for non sound portition */ if (!gpsycho) percep_energy[chn]=pe[chn]; /*************************************************************** * Check to see if we also need to compute long block thresholds ***************************************************************/ uselongblock[chn] = (pe[chn] < switch_pe); { double tot[3]={0,0,0}; double mn,mx; for ( j = HBLKSIZE_s/2; j < HBLKSIZE_s; j ++) for (sblock=0; sblock < 3; sblock++) tot[sblock]+=energy_s[sblock][j]; mn = minimum(tot[0],tot[1]); mn = minimum(mn,tot[2]); mx = maximum(tot[0],tot[1]); mx = maximum(mx,tot[2]); #ifdef HAVEGTK /* delay by one granule. Note we have to 'toggle' gr to do this */ if (gtkflag) { pinfo->ers[1-gr][chn]=ers_save[chn]; ers_save[chn]=mx/(1e-12+mn); pinfo->pe[1-gr][chn]=pe_save[chn]; pe_save[chn]=pe[chn]; } #endif #ifdef ENER_AWS if (gpsycho) { uselongblock[chn] = 1; /* big surge of energy - always use short blocks */ if ( mx > 25*mn) uselongblock[chn] = 0; /* switch based on pe, but only if there is some energy surge */ if (( mx > 2.5*mn ) && (pe[chn] > switch_pe)) uselongblock[chn]=0; } #endif } if ((chn == 1) && (force_ms)) { /* Forced ms_stereo mode. */ /* ch=0 (mid) blocktype determines ch=1 (side) blocktype */ uselongblock[1] = uselongblock[0]; } /*************************************************************** * compute masking thresholds * we need to always compute short block masking thresholds because * we dont know if this granule will be changed to a short block later. ***************************************************************/ if ( uselongblock[chn]) { /* no attack : use long blocks */ /* threshold calculation (part 2) */ for ( sb = 0; sb < SBMAX_l; sb++ ) { en[sb] = w1_l[sb] * eb[bu_l[sb]] + w2_l[sb] * eb[bo_l[sb]]; thm[sb] = w1_l[sb] *thr[bu_l[sb]] + w2_l[sb] * thr[bo_l[sb]]; for ( b = bu_l[sb]+1; b < bo_l[sb]; b++ ) { en[sb] += eb[b]; thm[sb] += thr[b]; } if ( en[sb] != 0.0 ) ratio[chn][sb] = thm[sb]/en[sb]; else ratio[chn][sb] = 0.0; } #ifdef HAVEGTK /* delay by one granule. Note we have to 'toggle' gr to do this */ if (gtkflag) { for (sb=0; sb< SBMAX_l; sb ++ ) { pinfo->thr[1-gr][chn][sb]=thm_save[chn][sb]; pinfo->en[1-gr][chn][sb]=en_save[chn][sb]; thm_save[chn][sb]=thm[sb]; en_save[chn][sb]=en[sb]; } } #endif for (sb=0; sb< SBMAX_l; sb ++ ) { thm_save[chn][sb]=thm[sb]; en_save[chn][sb]=en[sb]; } } /* in some cases, when computing the next granule, we may switch this * granule to a short block. compute short block thresholds just in case */ /*else*/ if ( gpsycho || !uselongblock[chn]) { /* threshold calculation for short blocks */ for ( sblock = 0; sblock < 3; sblock++ ) { for ( b = 0; b < CBANDS_s; b++ ) { eb[b] = 0.0; ecb[b] = 0.0; } for ( j = 0; j < HBLKSIZE_s; j++ ) eb[partition_s[j]] += energy_s[sblock][j]; for ( b = 0; b < CBANDS_s; b++ ) for ( k = 0; k < CBANDS_s; k++ ) ecb[b] += s3_l[b][k] * eb[k]; for ( b = 0; b < CBANDS_s; b++ ) { if (gpsycho) nb[b] = ecb[b] * norm_s[b] * exp( (double) SNR_s[b] * LN_TO_LOG10 ); else nb[b] = ecb[b] * norm_l[b] * exp( (double) SNR_s[b] * LN_TO_LOG10 ); thr[b] = maximum (qthr_s[b],nb[b]); } for ( sb = 0; sb < SBMAX_s; sb++ ) { en[sb] = w1_s[sb] * eb[bu_s[sb]] + w2_s[sb] * eb[bo_s[sb]]; thm[sb] = w1_s[sb] *thr[bu_s[sb]] + w2_s[sb] * thr[bo_s[sb]]; for ( b = bu_s[sb]+1; b < bo_s[sb]; b++ ) { en[sb] += eb[b]; thm[sb] += thr[b]; } if ( en[sb] != 0.0 ) ratio_s[chn][sb][sblock] = thm[sb]/en[sb]; else ratio_s[chn][sb][sblock] = 0.0; #ifdef HAVEGTK /* delay by one granule. Note we have to 'toggle' gr to do this */ if (gtkflag) { pinfo->thr_s[1-gr][chn][3*sb+sblock]=thm_s_save[chn][sb][sblock]; pinfo->en_s[1-gr][chn][3*sb+sblock]=en_s_save[chn][sb][sblock]; } #endif thm_s_save[chn][sb][sblock]=thm[sb]; en_s_save[chn][sb][sblock]=en[sb]; } } } /* compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper */ if (force_ms) { if (chn == 1) { double rside,rmid,mld; if ( uselongblock[chn]) { for ( sb = 0; sb < SBMAX_l; sb++ ) { mld = mld_l[sb]; rmid = Max(ratio[0][sb],Min(ratio[1][sb],mld)); rside = Max(ratio[1][sb],Min(ratio[0][sb],mld)); ratio[0][sb]=rmid; ratio[1][sb]=rside; } } /* alwasy compute these - we may need them later */ for ( sblock = 0; sblock < 3; sblock++ ){ for ( sb = 0; sb < SBMAX_s; sb++ ) { mld = mld_s[sb]; rmid = Max(ratio_s[0][sb][sblock],Min(ratio_s[1][sb][sblock],mld)); rside = Max(ratio_s[1][sb][sblock],Min(ratio_s[0][sb][sblock],mld)); ratio_s[0][sb][sblock]=rmid; ratio_s[1][sb][sblock]=rside; } } } } } /* end loop over chn */ #if 0 /* determin ms_ratio from masking thresholds*/ { double sidetot=0,tot=0,side,mid; for (sb= 15 ; sb< SBMAX_l; sb ++ ) { side = thm_save[0][sb]-thm_save[1][sb]; mid = thm_save[0][sb]+thm_save[1][sb]; sidetot += side*side; tot += side*side + mid*mid; } ms_ratio_l = Max(.875*ms_ratio_l,1.2*sidetot/(1e-10+tot)); sidetot=0; tot=0; for ( sblock = 0; sblock < 3; sblock++ ) for ( sb = 9; sb < SBMAX_s; sb++ ) { side = thm_s_save[0][sb][sblock]-thm_s_save[1][sb][sblock]; mid = thm_s_save[0][sb][sblock]+thm_s_save[1][sb][sblock]; sidetot += side*side; tot += side*side + mid*mid; } ms_ratio_s = Max(.875*ms_ratio_s,1.2*sidetot/(1e-10+tot)); } #endif /*************************************************************** * determin final block type ***************************************************************/ for (chn=0; chn<stereo; chn++) { blocktype[chn] = NORM_TYPE; } if (!allow_diff_short) if (info->mode==MPG_MD_JOINT_STEREO) { /* force both channels to use the same block type */ /* this is necessary if the frame is to be encoded in ms_stereo. */ /* But even without ms_stereo, FhG does this */ int bothlong= (uselongblock[0] && uselongblock[1]); if (!bothlong) { uselongblock[0]=0; uselongblock[1]=0; } } /* update the blocktype of the previous granule, since it depends on what * happend in this granule */ for (chn=0; chn<stereo; chn++) { if ( uselongblock[chn]) { /* no attack : use long blocks */ switch( blocktype_old[chn] ) { case NORM_TYPE: case STOP_TYPE: blocktype[chn] = NORM_TYPE; break; case SHORT_TYPE: blocktype[chn] = STOP_TYPE; break; case START_TYPE: fprintf( stderr, "Error in block selecting\n" ); abort(); break; /* problem */ } } else { /* attack : use short blocks */ blocktype[chn] = SHORT_TYPE; if ( blocktype_old[chn] == NORM_TYPE ) { blocktype_old[chn] = START_TYPE; } if ( blocktype_old[chn] == STOP_TYPE ) { blocktype_old[chn] = SHORT_TYPE ; } } blocktype_d[chn] = blocktype_old[chn]; /* value returned to calling program */ blocktype_old[chn] = blocktype[chn]; /* save for next call to l3psy_anal */ } if (blocktype_d[0]==2) *ms_ener_ratio = ms_ratio_s_old; else *ms_ener_ratio = ms_ratio_l_old; ms_ratio_s_old = ms_ratio_s; ms_ratio_l_old = ms_ratio_l; } extern double psy_data[]; void L3para_read(double sfreq, int *numlines, int *partition_l, double *minval, double *qthr_l, double *norm_l, double (*s3_l)[63], int *partition_s, double *qthr_s, double *norm_s, double *SNR, int *cbw_l, int *bu_l, int *bo_l, double *w1_l, double *w2_l, int *cbw_s, int *bu_s, int *bo_s, double *w1_s, double *w2_s) { double freq_tp; static double bval_l[CBANDS], bval_s[CBANDS]; int cbmax=0, cbmax_tp; static double s3_s[CBANDS][CBANDS]; double *p = psy_data; int sbmax ; int i,j,k,k2,loop, part_max ; /* Read long block data */ for(loop=0;loop<6;loop++) { freq_tp = *p++; cbmax_tp = (int) *p++; cbmax_tp++; if (sfreq == freq_tp ) { cbmax = cbmax_tp; for(i=0,k2=0;i<cbmax_tp;i++) { j = (int) *p++; numlines[i] = (int) *p++; minval[i] = *p++; qthr_l[i] = *p++; norm_l[i] = *p++; bval_l[i] = *p++; if (j!=i) { printf("1. please check \"psy_data\""); exit(-1); } for(k=0;k<numlines[i];k++) partition_l[k2++] = i ; } } else p += cbmax_tp * 6; } /************************************************************************ * Now compute the spreading function, s[j][i], the value of the spread-* * ing function, centered at band j, for band i, store for later use * ************************************************************************/ part_max = cbmax ; for(i=0;i<part_max;i++) { double tempx,x,tempy,temp; for(j=0;j<part_max;j++) { tempx = (bval_l[i] - bval_l[j])*1.05; if (j>=i) tempx = (bval_l[i] - bval_l[j])*3.0; else tempx = (bval_l[i] - bval_l[j])*1.5; /* if (j>=i) tempx = (bval_l[j] - bval_l[i])*3.0; else tempx = (bval_l[j] - bval_l[i])*1.5; */ if(tempx>=0.5 && tempx<=2.5) { temp = tempx - 0.5; x = 8.0 * (temp*temp - 2.0 * temp); } else x = 0.0; tempx += 0.474; tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); if (tempy <= -60.0) s3_l[i][j] = 0.0; else s3_l[i][j] = exp( (x + tempy)*LN_TO_LOG10 ); } } /* Read short block data */ for(loop=0;loop<6;loop++) { freq_tp = *p++; cbmax_tp = (int) *p++; cbmax_tp++; if (sfreq == freq_tp ) { cbmax = cbmax_tp; for(i=0,k2=0;i<cbmax_tp;i++) { j = (int) *p++; numlines[i] = (int) *p++; qthr_s[i] = *p++; norm_s[i] = *p++; SNR[i] = *p++; bval_s[i] = *p++; if (j!=i) { printf("3. please check \"psy_data\""); exit(-1); } for(k=0;k<numlines[i];k++) partition_s[k2++] = i ; } } else p += cbmax_tp * 6; } /************************************************************************ * Now compute the spreading function, s[j][i], the value of the spread-* * ing function, centered at band j, for band i, store for later use * ************************************************************************/ part_max = cbmax ; for(i=0;i<part_max;i++) { double tempx,x,tempy,temp; for(j=0;j<part_max;j++) { tempx = (bval_s[i] - bval_s[j])*1.05; if (j>=i) tempx = (bval_s[i] - bval_s[j])*3.0; else tempx = (bval_s[i] - bval_s[j])*1.5; if(tempx>=0.5 && tempx<=2.5) { temp = tempx - 0.5; x = 8.0 * (temp*temp - 2.0 * temp); } else x = 0.0; tempx += 0.474; tempy = 15.811389 + 7.5*tempx - 17.5*sqrt(1.0+tempx*tempx); if (tempy <= -60.0) s3_s[i][j] = 0.0; else s3_s[i][j] = exp( (x + tempy)*LN_TO_LOG10 ); } } /* Read long block data for converting threshold calculation partitions to scale factor bands */ for(loop=0;loop<6;loop++) { freq_tp = *p++; sbmax = (int) *p++; sbmax++; if (sfreq == freq_tp) { for(i=0;i<sbmax;i++) { j = (int) *p++; cbw_l[i] = (int) *p++; bu_l[i] = (int) *p++; bo_l[i] = (int) *p++; w1_l[i] = (double) *p++; w2_l[i] = (double) *p++; if (j!=i) { printf("30:please check \"psy_data\"\n"); exit(-1); } if (i!=0) if ( (bo_l[i] != (bu_l[i]+cbw_l[i])) || (fabs(1.0-w1_l[i]-w2_l[i-1]) > 0.01 ) ) { printf("31l: please check \"psy_data.\"\n"); exit(-1); } } } else p += sbmax * 6; } /* Read short block data for converting threshold calculation partitions to scale factor bands */ for(loop=0;loop<6;loop++) { freq_tp = *p++; sbmax = (int) *p++; sbmax++; if (sfreq == freq_tp) { for(i=0;i<sbmax;i++) { j = (int) *p++; cbw_s[i] = (int) *p++; bu_s[i] = (int) *p++; bo_s[i] = (int) *p++; w1_s[i] = *p++; w2_s[i] = *p++; if (j!=i) { printf("30:please check \"psy_data\"\n"); exit(-1); } if (i!=0) if ( (bo_s[i] != (bu_s[i]+cbw_s[i])) || (fabs(1.0-w1_s[i]-w2_s[i-1]) > 0.01 ) ) { printf("31s: please check \"psy_data.\"\n"); exit(-1); } } } else p += sbmax * 6; } } void sprdngf1(dest,source) FLOAT *dest; double *source; { #ifdef GOOBER static int mfcinit = 0; #endif int b,k; extern double s3_l[CBANDS][CBANDS]; /* s3_l is a sparse matrix. fudge with it for 44.1 khz */ static int s3ind[CBANDS][2] = { {0,2}, {0,3}, {0,4}, {0,5}, {0,6}, {0,7}, {0,8}, {0,9}, {0,10}, {0,11}, {0,12}, {1,14}, {1,14}, {2,15}, {3,15}, {5,16}, {6,17}, {7,19}, {9,20}, {10,21}, {11,22}, {12,23}, {14,24}, {15,25}, {15,27}, {16,28}, {16,28}, {17,29}, {18,30}, {19,31}, {19,32}, {20,34}, {21,35}, {22,36}, {22,36}, {23,37}, {24,38}, {25,39}, {26,41}, {27,42}, {28,43}, {29,44}, {30,45}, {31,46}, {32,47}, {33,48}, {34,49}, {35,50}, {36,51}, {37,52}, {37,53}, {38,54}, {39,55}, {40,56}, {41,57}, {42,58}, {43,59}, {44,60}, {45,61}, {46,62}, {47,62}, {48,62}, {48,62}, }; for ( b = 0;b < CBANDS; b++ ) for ( k = s3ind[b][0]; k <= s3ind[b][1]; k++ ) dest[b] += s3_l[b][k] * source[k]; #ifdef GOOBER if (mfcinit==0) { mfcinit++; for (b=0;b<CBANDS;b++) { fprintf("{",b); for (k=0;k<CBANDS;k++) { if (fabs(s3_l[b][k])>0.00000001) fprintf("%i ",k); } fprintf("\n"); } } #endif /* GOOBER */ } void sprdngf2(dest,source) double *dest; FLOAT *source; { int b,k; extern double s3_l[CBANDS][CBANDS]; /* s3_l is a sparse matrix. fudge with it for 44.1 khz */ static int s3ind[CBANDS][2] = { {0,2}, {0,3}, {0,4}, {0,5}, {0,6}, {0,7}, {0,8}, {0,9}, {0,10}, {0,11}, {0,12}, {1,14}, {1,14}, {2,15}, {3,15}, {5,16}, {6,17}, {7,19}, {9,20}, {10,21}, {11,22}, {12,23}, {14,24}, {15,25}, {15,27}, {16,28}, {16,28}, {17,29}, {18,30}, {19,31}, {19,32}, {20,34}, {21,35}, {22,36}, {22,36}, {23,37}, {24,38}, {25,39}, {26,41}, {27,42}, {28,43}, {29,44}, {30,45}, {31,46}, {32,47}, {33,48}, {34,49}, {35,50}, {36,51}, {37,52}, {37,53}, {38,54}, {39,55}, {40,56}, {41,57}, {42,58}, {43,59}, {44,60}, {45,61}, {46,62}, {47,62}, {48,62}, {48,62}, }; for ( b = 0;b < CBANDS; b++ ) for ( k = s3ind[b][0]; k <= s3ind[b][1]; k++ ) dest[b] += s3_l[b][k] * source[k]; }